package com.sparrow.common.attr;

import com.sparrow.common.attr.domain.*;
import com.sparrow.common.attr.listener.AttrChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 属性盒子
 * 增量计算：只处理变化部分，性能高
 * 树结构缓存：attrSumMap 缓存子节点属性，查询 O(子树大小)
 * 监听机制：可响应单条路径属性变化
 * 模块化路径：通过 AttrInst 支持不同实例或子路径区分
 *
 * 统计某个模块的属性时，把所有该模块的所有子实例的属性加上
 */
public class AttrBox {
    /**
     * 根节点
     */
    private final AttrModule root;
    /**
     * 路径自己本身的属性，用于替换属性时计算差值
     */
    private final Map<AttrModuleInst, Attr> attrMap = new HashMap<>();
    /**
     * 路径属性汇总 包含了子路径的属性
     */
    private Map<AttrModuleInst, Attr> attrSumMap = new HashMap<>();
    /**
     * 总属性
     */
    private final Attr total = new Attr();
    /**
     * 监听器
     */
    private final List<AttrChangeListener> listeners = new ArrayList<>();

    private Map<AttrModule, List<AttrModuleInst>> instMap = new HashMap<>();

    public AttrBox(AttrModule root) {
        this.root = root;
        assignIndex(root, new AtomicInteger(0));
    }

    public void initModuleInst(AttrModule module) {

    }

    public void addAttrChangeListener(AttrChangeListener listener) {
        listeners.add(listener);
    }

    public void removeAttrChangeListener(AttrChangeListener listener) {
        listeners.remove(listener);
    }

    private void notifyAttrChanged(AttrModuleInst inst, Attr diff) {
        for (AttrChangeListener listener : listeners) {
            listener.onAttrChanged(inst, diff);
        }
    }

    /**
     * 分配index 父index < 子index
     * @param module
     * @param indexCounter
     */
    private void assignIndex(AttrModule module, AtomicInteger indexCounter) {
        module.index = indexCounter.incrementAndGet();
        for (AttrModule child : module.children) {
            assignIndex(child, indexCounter);
        }
        if (module.children.size() > 0) {
            AttrModule lastChild = module.children.get(module.children.size() - 1);
            module.subtreeIndexMax = lastChild.index;
        }
    }



    /**
     * 设置某个实例的属性值，更新差值同步到总属性
     * @param inst
     * @param newAttr
     */
    public void setAttr(AttrModuleInst inst, Attr newAttr) {
        Attr oldAttr = attrMap.get(inst);
        if (oldAttr == null) {
            oldAttr = Attr.EMPTY; // 静态不可变空对象，避免 new
        }
        Attr diff = newAttr.copy();
        diff.subtract(oldAttr);//属性差值
        if (diff.isEmpty()) {
            return;
        }

        if (newAttr.isEmpty()) {
            attrMap.remove(inst);
        } else {
            attrMap.put(inst, newAttr);
        }
        // 向上传播缓存（递归往上加差值）
        propagateAttr(inst, diff);
        total.add(diff);//总属性插值
        //通知属性变化
        notifyAttrChanged(inst, diff);
    }

    /**
     * 移除实例属性
     * @param inst
     */
    public void removeAttr(AttrModuleInst inst) {
        setAttr(inst, Attr.EMPTY);
    }

    /**
     * 递归更新父实例属性缓存
     * @param inst
     * @param diff
     */
    private void propagateAttr(AttrModuleInst inst, Attr diff) {
        attrSumMap.merge(inst, diff, (oldVal, newVal) -> {
            oldVal.add(newVal);
            return oldVal;
        });
        if (inst.parent != null) {
            propagateAttr(inst.parent, diff);
        }
    }

    /**
     * 获取总属性（所有路径属性合计）
     * @return
     */
    public Attr getTotalAttr() {
        return total;
    }

    /**
     * 获取某个模块（包括子模块）所有路径的属性和
     * @param module
     * @return
     */
    public Attr getAttrByModule(AttrModule module) {
        Attr sum = new Attr();

        for (Map.Entry<AttrModuleInst, Attr> entry : attrMap.entrySet()) {
            AttrModuleInst r = entry.getKey();
            if (r.module.index == module.index || isDescendant(module, r.module)) {
                sum.add(entry.getValue());
            }
        }
        return sum;
    }

    /**
     * tar 是否是 module 的后代
     * @param module
     * @param tar
     * @return
     */
    public boolean isDescendant(AttrModule module, AttrModule tar) {
        return tar.index > module.index && tar.index <= module.subtreeIndexMax;
    }

    /**
     * 获取属性模块实例对应的属性
     * @param inst
     * @return
     */
    public Attr getAttrByInst(AttrModuleInst inst) {
        return attrSumMap.get(inst);
    }

    /**
     * 获取实例自身属性(不包含子实例的属性)
     * @param inst
     * @return
     */
    public Attr getAttrExcludeChild(AttrModuleInst inst) {
        return attrMap.get(inst);
    }

    /**
     * 打印整个模块树的 index 和 childIndexMax
     * @param node 根节点
     */
    public void printModuleTreeIndex(AttrModule node) {
        printModuleTreeIndex(node, 0);
    }

    private void printModuleTreeIndex(AttrModule node, int level) {
        // 构建缩进
        StringBuilder indent = new StringBuilder();
        for (int i = 0; i < level; i++) {
            indent.append("  "); // 每级两个空格
        }

        System.out.println(indent.toString() + node.name
                + " [index=" + node.index
                + ", childIndexMax=" + node.subtreeIndexMax + "]");

        // 递归打印子节点
        for (AttrModule child : node.children) {
            printModuleTreeIndex(child, level + 1);
        }
    }

    public Attr getFinalAttr() {
        // 1. 复制总属性作为基础
        Attr finalAttr = total.copy();

        // 2. 遍历所有实例的属性
        for (Map.Entry<AttrModuleInst, Attr> entry : attrMap.entrySet()) {
            AttrModuleInst inst = entry.getKey();
            Attr attr = entry.getValue();

            attr.walkValue((type, value) -> {
                if (!type.isPercent()) return; // 非百分比跳过
                IAttrType baseType = type.affectType();
                AttrScope scope = type.getPercentScope();
                long baseValue;
                switch (scope) {
                    case INSTANCE:
                        // 只作用在当前实例自身
                        baseValue = getAttrExcludeChild(inst).get(baseType);
                        finalAttr.add(baseType, baseValue * value / 10000);
                        break;
                    case MODULE:
                        // 作用于当前模块（含子实例）
                        baseValue = getAttrByModule(inst.module).get(type);
                        finalAttr.add(baseType, baseValue * value / 10000);
                        break;
                    case GLOBAL:
                        // 作用于总属性
                        baseValue = total.get(baseType);
                        finalAttr.add(baseType, baseValue * value / 10000);
                        break;
                }
            });
        }

        return finalAttr;
    }

}
